#ifndef __pty_kenny_dkfjiwoo3w3__
#define __pty_kenny_dkfjiwoo3w3__

#include <hude/utils/pty.hpp>

#include "brick/brick.hpp"

namespace ha
{
    namespace brick
    {
        /*********************************************************************
         * @brief 虚拟控制台， 这里一般做为虚拟串口
         */
        class pty_t :
            public _brick_aio_t< pty_t >
        {
        public:
            pty_t( aio_t aio, const json_t& args ) :
                _brick_aio_t< pty_t >( aio ), pty_( O_RDWR | O_NOCTTY | O_NDELAY ), master_( pty_.master() )
            {
                if( this->settings( args ) )
                {
                    this->mount( pty_.native() );
                }
            }

            ~pty_t()
            {
                this->unmount( pty_.native() );

                if( ! link_.empty() )
                {
                    auto ret = unlink( link_.c_str() );

                    if( ret )
                    {
                        llog_err( "<brick>", "ERROR: unlink %s.", link_.c_str() );
                    }
                }
            }

            int recv( void* p, size_t n ) { return master_->recv( p, n ); }

            int send( const void* p, size_t n ) override { return master_->send( p, n ); }

            void close() override { master_->close(); }

            bool settings( const json_t& args ) override;

            bool ok() const { return !!pty_; }
            const std::string& name() const { return link_; }

        private:
            hude::utils::pty_t pty_;
            hude::utils::pt_t  master_;
            std::string link_;
        };

        /*********************************************************************
         * @brief 设置pty参数
         */
        inline bool pty_t::settings( const json_t& args )
        {
            set_noblock( pty_.native() );

            master_->echo( false );

            auto link = hude::utils::json_path_t::value< std::string >( args, "link" );

            if( link )
            {
                link_ = *link;

                ::unlink( link_.c_str() );

                if( ::symlink( pty_.ptsname(), link_.c_str() ) )
                {
                    llog_err( "<brick>", "\t ERROR: <brick> pty( master: %d, name: %s --> %s ), create link failed.", pty_.native(), pty_.ptsname(), link_.c_str() );

                    return false;
                }

                llog_nte( "<brick>", "\t SUCCESS: <brick> pty( master: %d, name: %s --> %s )", pty_.native(), pty_.ptsname(), link_.c_str() );
            }

            ::chmod( pty_.ptsname(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );

            return true;
        }

    } //namespace brick
} //namespace ha

#endif //__pty_kenny_dkfjiwoo3w3__
